package com.ts.api.module.api.service.impl;

import com.gitee.apanlh.util.algorithm.digest.MD5;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.ts.api.common.constant.api.ApiBizTypeEnum;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.constant.api.ApiServiceCodeEnum;
import com.ts.api.common.constant.productflow.ProductApplyFlowSrcTypeEnum;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.common.context.ApiContext;
import com.ts.api.common.localcache.DistrictCache;
import com.ts.api.common.redis.DataExchangeRedisKey;
import com.ts.api.common.util.H5DomainUrlUtils;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.convert.core.http.client.ApiHttpMessage;
import com.ts.api.module.api.convert.plan.http.ApiPlanHttpHandler;
import com.ts.api.module.api.convert.receive.entity.ApiReceiveApply;
import com.ts.api.module.api.convert.receive.entity.ApiReceiveDecrypt;
import com.ts.api.module.api.convert.receive.entity.ApiReceivePhoneMd5DataExchange;
import com.ts.api.module.api.convert.receive.handler.DelegatingApiReceivePhoneMd5ConvertHandler;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.bo.ApiCustomPushBO;
import com.ts.api.module.api.entity.bo.ApiDataExchangeBO;
import com.ts.api.module.api.entity.bo.ApiKeyAmountBO;
import com.ts.api.module.api.entity.bo.ApiParameterBO;
import com.ts.api.module.api.entity.bo.ApiPreRequiredBO;
import com.ts.api.module.api.entity.bo.ApiRequiredFlowBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.api.entity.vo.ReqApiParameterVO;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.api.service.ApiKeyAmountService;
import com.ts.api.module.api.service.ApiReceiveCustomPushService;
import com.ts.api.module.api.service.ApiUserRegister;
import com.ts.api.module.api.wake.WakeRatioService;
import com.ts.api.module.channel.entity.po.ChannelUserFormFieldPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.channel.entity.qo.ChannelUserQO;
import com.ts.api.module.channel.service.ChannelFormService;
import com.ts.api.module.channel.service.ChannelUserService;
import com.ts.api.module.common.entity.DistrictPO;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeField;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeResult;
import com.ts.api.module.product.biz.ProductMatchBiz;
import com.ts.api.module.product.entity.bo.ProductAmountBO;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import com.ts.api.module.product.service.ProductAmountService;
import com.ts.api.module.product.service.ProductApplyFlowService;
import com.ts.api.module.product.service.ProductPlanService;
import com.ts.api.module.product.service.ProductPlanTypeService;
import com.ts.api.module.product.service.ProductService;
import com.ts.api.task.org.OrgWakeTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
public class ApiReceiveCustomPushServiceImpl implements ApiReceiveCustomPushService {

    @Autowired
    private DelegatingApiReceivePhoneMd5ConvertHandler delegatingApiReceivePhoneMd5ConvertHandler;
    @Autowired
    private ChannelUserService channelUserService;
    @Autowired
    private ProductApplyFlowService productApplyFlowService;
    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductPlanService productPlanService;
    @Autowired
    private ProductAmountService productAmountService;
    @Autowired
    private ApiKeyAmountService apiKeyAmountService;
    @Autowired
    private ApiPlanHttpHandler apiPlanHttpHandler;
    @Autowired
    private ProductMatchBiz productMatchBiz;
    @Autowired
    private ProductPlanTypeService productPlanTypeService;
    @Autowired
    private ChannelFormService channelFormService;
    @Autowired
    private WakeRatioService wakeRatioService;
    @Autowired
    private ApiUserRegister apiUserRegister;

    @Override
    public Map<String, Object> dataExchange(ApiCustomPushBO apiCustomPushBO) throws ApiMsgException {
        try {
            ApiKeyPO apiKeyPO = apiCustomPushBO.getApiKeyPO();

            ApiContext.SERVICE_CODE.set(ApiServiceCodeEnum.A0001.getCode());

            String apiClientId = apiKeyPO.getApiClientId();
            Long productId = apiCustomPushBO.getProductId();
            RequestVO requestVO = apiCustomPushBO.getRequestVO();
            String reqId = ApiContext.REQ_ID.get();

            //  解析参数
            Map<String, String> map = delegatingApiReceivePhoneMd5ConvertHandler.requireParam(requestVO);
            //  解密参数
            ApiReceiveDecrypt decrypt = delegatingApiReceivePhoneMd5ConvertHandler.decrypt(map, requestVO);
            //  设置日志解密数据
            ApiContext.DECRYPT_DATA.set(decrypt.getData());
            //  撞库参数-转换API参数
            ApiUserRequest apiUserRequest = delegatingApiReceivePhoneMd5ConvertHandler.parseDataExchange(decrypt);
            if (ValidParam.isEmpty(apiUserRequest.getCity())) {
                apiUserRequest.setCity("定制渠道");
            }
            apiUserRequest.setApiClientId(apiClientId);

            //  是否本地库存在
            String phoneMd5 = apiUserRequest.getPhoneMd5();
            Assert.isNotEmptyThrows(phoneMd5, new ApiMsgException(ApiEnum.API_NULL_FAIL.format("phoneMd5", "不可为null")));

            //  指定主体撞库
            //  如果出现并发时将此次流程放弃，抛出异常
            boolean absent = DataExchangeRedisKey.CUSTOM_PHONE_MD5.setIfAbsentForSeconds(phoneMd5, "1", 3L);
            Assert.isTrueThrows(absent, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_DISCARD));

            //  是否本地库已存在
            boolean hasLocalExist = channelUserService.hasLocalExist(phoneMd5);
            // 唤醒
            hasLocalExist = this.wakeRatioService.wake(apiClientId, apiKeyPO.getApiWakeRatio().intValue(), hasLocalExist);
            apiUserRequest.setExistLocal(ClassConvertUtils.toStr(hasLocalExist));

            ReqApiParameterVO apiRequestVO = ReqApiParameterVO.create(apiUserRequest, apiKeyPO);
            ApiContext.REQ_PARAMS.set(apiRequestVO);

            //  获取固定主体机构
            ProductPO productPO = productService.get(productId);
            Assert.isNotNullThrows(productPO, new ApiMsgException(ApiEnum.API_NULL_FAIL.format("org", "获取org不可为null")));

            //  获取该主体下的计划
            List<ProductPlanPO> listPlan = productPlanService.listByProductId(productId);
            Assert.isNotEmptyThrows(listPlan, new ApiMsgException(ApiEnum.API_NULL_FAIL.format("plan", "获取plan不可为null")));
            List<ProductPlanPO> listPlanFirst = CollUtils.newArrayList(listPlan.getFirst());

            //  记录流程实体
            ProductApplyFlowPO productApplyFlowPO = new ProductApplyFlowPO();
            productApplyFlowPO.setApiClientId(apiKeyPO.getApiClientId());
            productApplyFlowPO.setLoanChannelId(apiKeyPO.getLoanChannelId());
            productApplyFlowPO.setReqId(ClassConvertUtils.toLong(reqId));
            productApplyFlowPO.setSrcType(ProductApplyFlowSrcTypeEnum.API.getType());
            productApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.CHANNEL_DATA_EXCHANGE.getType());
            productApplyFlowPO.setPhoneMd5(phoneMd5);
            productApplyFlowPO.setCreateTime(DateUtils.currentTime());

            //  根据当前渠道查询以往流程中所属关联机构计划
            List<ProductApplyFlowPO> listFlow = apiBizRequiredService.existFailFlow(apiKeyPO.getApiClientId(), phoneMd5);
            ProductApplyFlowPO findDataExchangeSucFlow = CollUtils.findOne(listFlow, t -> Eq.object(ProductApplyFlowStatusEnum.CHANNEL_DATA_EXCHANGE.getType(), t.getStatus()));
            boolean existFlow = ValidParam.isNotNull(findDataExchangeSucFlow);

            //  主体计划分发
            ProductPlanPO productPlanPO = productMatchBiz.apiAllocateByPrice(apiKeyPO, apiRequestVO, listPlanFirst);

            //  记录进件流程表
            productApplyFlowPO.setLoanProductId(productPlanPO.getLoanProductId());
            productApplyFlowPO.setLoanProductPlanId(productPlanPO.getId());
            String city = apiRequestVO.getFormMap().get("city");
            if (ValidParam.isNotNull(city)) {
                DistrictPO districtPO = DistrictCache.getByName(city);
                productApplyFlowPO.setAreaCode(districtPO.getCode());
                productApplyFlowPO.setAreaName(districtPO.getName());
            }

            //  不存在记录时插入
            if (!existFlow) {
                productApplyFlowService.insert(productApplyFlowPO, false);
            }

            //  构建分发返回实体
            PlanDistributeResult planDistributeResult = PlanDistributeResult.ofEmptySuc();
            planDistributeResult.setProductPO(productPO);
            planDistributeResult.setProductPlanPO(productPlanPO);
            planDistributeResult.setCurrentDistributeFlow(productApplyFlowPO);
            planDistributeResult.setReqId(reqId);
            PlanDistributeField planDistributeField = PlanDistributeField.ofOrgPhoneMd5(productPO, productPlanPO, reqId);
            planDistributeResult.setPlanDistributeField(planDistributeField);

            //  业务返回处理
            ApiDataExchangeBO apiDataExchangeBO = ApiDataExchangeBO.of(planDistributeResult);
            ApiReceivePhoneMd5DataExchange message = ApiReceivePhoneMd5DataExchange.create(apiDataExchangeBO, apiKeyPO);

            //  撞库消息设置是否存在本地库
            message.setHasLocalExist(hasLocalExist);

            //  如果本地库存在则返回失败
            if (hasLocalExist) {
                message.setBizMsg("匹配流程失败");
                message.setBizCode(1000);
                this.wakeApply(phoneMd5, productPO, productPlanPO, productApplyFlowPO);
            }
            return delegatingApiReceivePhoneMd5ConvertHandler.respDataExchange(message);
        }  catch (Exception e) {
            ApiMsgException apiMsgException;
            if (e instanceof ApiMsgException) {
                apiMsgException = ((ApiMsgException) e);
            } else {
                apiMsgException = new ApiMsgException(ApiEnum.API_EXP_ERROR, e);
            }

            apiMsgException.setReceiveMode(true);
            ApiReceivePhoneMd5DataExchange failMessage = ApiReceivePhoneMd5DataExchange.fail(apiMsgException.getApiMsg(), apiMsgException.getApiCode());
            Map<String, Object> result = delegatingApiReceivePhoneMd5ConvertHandler.respDataExchange(failMessage);
            apiMsgException.setReceiveData(result);
            throw apiMsgException;
        }
    }

    @Override
    public Map<String, Object> apply(ApiCustomPushBO apiCustomPushBO) throws ApiMsgException {
        try {
            ApiKeyPO apiKeyPO = apiCustomPushBO.getApiKeyPO();

            ApiContext.SERVICE_CODE.set(ApiServiceCodeEnum.A0002.getCode());

            String apiClientId = apiKeyPO.getApiClientId();
            Long productId = apiCustomPushBO.getProductId();
            RequestVO requestVO = apiCustomPushBO.getRequestVO();

            //  设置日志解密数据
            Map<String, String> map = delegatingApiReceivePhoneMd5ConvertHandler.requireParam(requestVO);
            ApiReceiveDecrypt decrypt = delegatingApiReceivePhoneMd5ConvertHandler.decrypt(map, requestVO);
            ApiContext.DECRYPT_DATA.set(decrypt.getData());

            // 创建Api参数
            ApiUserRequest apiUserRequest = delegatingApiReceivePhoneMd5ConvertHandler.parseApply(decrypt);
            apiUserRequest.setApiClientId(apiClientId);
            ReqApiParameterVO reqApiParameterVO = ReqApiParameterVO.create(apiUserRequest, apiKeyPO);
            ApiContext.REQ_PARAMS.set(reqApiParameterVO);

            //  查询是否渠道存在该流程
            String phoneMd5 = MD5.create().digestToHex(apiUserRequest.getPhone());
            //  查询是否渠道存在该流程
            ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByApiClientId(phoneMd5, apiKeyPO.getApiClientId());
            ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
            Assert.isNotNullThrows(productApplyFlowPO, new ApiMsgException(ApiEnum.API_APPLY_FLOW_ERROR));

            //  增加进件前置参数验证
            ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.OLD_APPLY, null, ApiBizMatchBO.createNormalPlanApply());
            ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParam(apiPreRequiredBO);

            //  是否本地库已存在
            boolean hasLocalExist = apiParameterBO.getHasLocalExist();
            if (!hasLocalExist) {
                //  注册用户
                apiUserRegister.applyUserRegister(apiParameterBO, productApplyFlowPO);
            }
            //  设置地区信息
            DistrictPO districtPO = DistrictCache.getByName(apiUserRequest.getCity());
            apiUserRequest.setAreaCode(districtPO.getCode());
            apiUserRequest.setProvinceCode(districtPO.getProvinceCode());
            apiUserRequest.setProvinceName(districtPO.getProvinceName());

            //  记录流程
            ProductApplyFlowPO insertProductApplyFlowPO = new ProductApplyFlowPO();
            insertProductApplyFlowPO.setApiClientId(productApplyFlowPO.getApiClientId());
            insertProductApplyFlowPO.setLoanChannelId(productApplyFlowPO.getLoanChannelId());
            insertProductApplyFlowPO.setLoanProductId(productApplyFlowPO.getLoanProductId());
            insertProductApplyFlowPO.setLoanProductPlanId(productApplyFlowPO.getLoanProductPlanId());
            insertProductApplyFlowPO.setReqId(productApplyFlowPO.getReqId());
            insertProductApplyFlowPO.setSrcType(ProductApplyFlowSrcTypeEnum.API.getType());
            insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.APPLY_ERROR.getType());
            insertProductApplyFlowPO.setPhoneMd5(productApplyFlowPO.getPhoneMd5());
            insertProductApplyFlowPO.setCreateTime(DateUtils.currentTime());
            insertProductApplyFlowPO.setBizStatus("0");
            insertProductApplyFlowPO.setAreaName(apiUserRequest.getCity());
            insertProductApplyFlowPO.setAreaCode(apiUserRequest.getAreaCode());

            //  获取固定主体机构
            ProductPO productPO = productService.get(productId);
            Assert.isNotNullThrows(productPO, new ApiMsgException(ApiEnum.API_NULL_FAIL.format("org", "获取org不可为null")));
            //  获取改主体下的计划
            List<ProductPlanPO> listPlan = productPlanService.listByProductId(productId);
            Assert.isNotEmptyThrows(listPlan, new ApiMsgException(ApiEnum.API_NULL_FAIL.format("plan", "获取plan不可为null")));
            //  获取固定第一条计划
            ProductPlanPO matchProductPlanPO = IteratorUtils.getFirst(listPlan);

            //  是否本地机构计划
            if (productPlanTypeService.hasLocalOrgPlan(productPO, matchProductPlanPO)) {
                insertProductApplyFlowPO.setCallUrl("本地甲方CRM");
            }

            if (productPlanTypeService.hasApiOrgPlan(productPO, matchProductPlanPO)) {
                Long reqId = insertProductApplyFlowPO.getReqId();
                //  设置API参数数据
                apiUserRequest.setProductId(insertProductApplyFlowPO.getLoanProductId());
                apiUserRequest.setProductPlanId(insertProductApplyFlowPO.getLoanProductPlanId());
                apiUserRequest.setLoanChannelId(insertProductApplyFlowPO.getLoanChannelId());
                apiUserRequest.setReqId(reqId.toString());
                //  发送进件
                ApiHttpMessage httpMessage = apiPlanHttpHandler.sendApply(apiUserRequest, productPO, matchProductPlanPO);
                insertProductApplyFlowPO.setCallUrl(productPO.getApiApplyUrl());
                insertProductApplyFlowPO.setReqData(String.valueOf(httpMessage.getRequestBody()));
                insertProductApplyFlowPO.setRespData(httpMessage.getResponseBody());
                insertProductApplyFlowPO.setRespCode(String.valueOf(httpMessage.getRespCode()));

                //  是否返回HTTP异常
                boolean hasHttpExp = apiBizRequiredService.hasHttpExp(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.APPLY_ERROR);
                if (hasHttpExp) {
                    throw new ApiMsgException(ApiEnum.API_RECEIVE_ORG_ERROR);
                }
                //  是否进件返回失败
                boolean hasHttpRespBizSuc = apiBizRequiredService.hasHttpRespBizSuc(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.APPLY_ERROR);
                if (!hasHttpRespBizSuc) {
                    throw new ApiMsgException(ApiEnum.API_RECEIVE_ORG_FAIL);
                }
            }

            //  查询用户信息
            ChannelUserQO userQO = ChannelUserQO.createPhoneMd5(phoneMd5);
            ChannelUserRegisterPO userRegisterPO = channelUserService.get(userQO);
            Long userId = userRegisterPO.getId();

            //  用户数据关联机构并记录流程数据
            insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.USER_ACCEPT.getType());
            insertProductApplyFlowPO.setBizStatus("1");
            apiUserRegister.uniqueBindProductUser(insertProductApplyFlowPO, userId);

            //  扣费
            ProductAmountBO productAmountBO = new ProductAmountBO();
            productAmountBO.setProductId(matchProductPlanPO.getLoanProductId());
            productAmountBO.setProductPlanId(matchProductPlanPO.getId());
            productAmountBO.setUserId(userRegisterPO.getId());
            productAmountBO.setPhoneMd5(userRegisterPO.getPhoneMd5());
            productAmountBO.setLoanChannelId(productApplyFlowPO.getLoanChannelId());
            productAmountBO.setApiClientId(productApplyFlowPO.getApiClientId());
            productAmountBO.setOriginalPrice(null);
            productAmountBO.setHasPlatform(Boolean.FALSE);
            productAmountBO.setHasLocalExist(apiParameterBO.getHasLocalExist());
            BigDecimal planPrice = productAmountService.deduct(productAmountBO);

            ApiKeyAmountBO apiKeyAmountBO = new ApiKeyAmountBO();
            apiKeyAmountBO.setProductId(matchProductPlanPO.getLoanProductId());
            apiKeyAmountBO.setProductPlanId(matchProductPlanPO.getId());
            apiKeyAmountBO.setUserId(userRegisterPO.getId());
            apiKeyAmountBO.setLoanChannelId(productApplyFlowPO.getLoanChannelId());
            apiKeyAmountBO.setApiClientId(productApplyFlowPO.getApiClientId());
            apiKeyAmountBO.setPhoneMd5(userRegisterPO.getPhoneMd5());
            apiKeyAmountBO.setPlanPrice(planPrice);
            apiKeyAmountBO.setHasPlatform(Boolean.FALSE);
            apiKeyAmountBO.setHasLocalExist(apiParameterBO.getHasLocalExist());
            apiKeyAmountService.deduct(apiKeyAmountBO);

            //  返回进件消息对象
            ApiReceiveApply apiReceiveApply = new ApiReceiveApply();
            apiReceiveApply.setApiClientId(productApplyFlowPO.getApiClientId());
            apiReceiveApply.setOrgName(productPO.getName());
            apiReceiveApply.setDisplayName(matchProductPlanPO.getDisplayName());
            apiReceiveApply.setPrice(matchProductPlanPO.getPrice());
            apiReceiveApply.setPhoneMd5(productApplyFlowPO.getPhoneMd5());
            apiReceiveApply.setPhone(userRegisterPO.getPhone());
            apiReceiveApply.setCallUrl(H5DomainUrlUtils.createH5CallUrl(productApplyFlowPO.getPhoneMd5(), productApplyFlowPO.getApiClientId()));
            apiReceiveApply.setProductApplyFlowPO(insertProductApplyFlowPO);
            apiReceiveApply.setBizMsg(ApiEnum.API_SIGN_SUC.getMsg());
            apiReceiveApply.setBizCode(ApiEnum.API_SIGN_SUC.getCode());
            apiReceiveApply.setHasLocalExist(false);
            return delegatingApiReceivePhoneMd5ConvertHandler.respApply(apiReceiveApply);
        } catch (Exception e) {
            ApiMsgException apiMsgException;
            if (e instanceof ApiMsgException) {
                apiMsgException = ((ApiMsgException) e);
            } else {
                apiMsgException = new ApiMsgException(ApiEnum.API_EXP_ERROR, e);
            }

            apiMsgException.setReceiveMode(true);
            ApiReceiveApply failMessage = ApiReceiveApply.fail(apiMsgException.getApiMsg(), apiMsgException.getApiCode());
            Map<String, Object> result = delegatingApiReceivePhoneMd5ConvertHandler.respApply(failMessage);
            apiMsgException.setReceiveData(result);
            throw apiMsgException;
        }
    }

    @Override
    public void wakeApply(String phoneMd5, ProductPO productPO, ProductPlanPO productPlanPO, ProductApplyFlowPO productApplyFlowPO) {
        //  临时异步执行
        OrgWakeTask.POOL.execute(() -> {
            final String finalPhoneMd5 = phoneMd5;
            final ProductPO finalProductPO = productPO;
            final ProductPlanPO finalProductPlanPO = productPlanPO;
            final ProductApplyFlowPO lastDataExchangeFlow = productApplyFlowPO;

            //  获取用户信息-资质
            ChannelUserRegisterPO userRegisterPO = channelUserService.get(ChannelUserQO.createPhoneMd5(finalPhoneMd5));

            List<ChannelUserFormFieldPO> listUserForm = channelFormService.listUserFormField(userRegisterPO.getId());
            //  获取API交互对象
            ApiUserRequest apiUserRequest = ApiUserRequest.convert(userRegisterPO, listUserForm);
            apiUserRequest.setApiClientId(lastDataExchangeFlow.getApiClientId());
            apiUserRequest.setProductId(lastDataExchangeFlow.getLoanProductId());
            apiUserRequest.setProductPlanId(lastDataExchangeFlow.getLoanProductPlanId());
            apiUserRequest.setReqId(String.valueOf(lastDataExchangeFlow.getReqId()));
            apiUserRequest.setExistLocal(StringUtils.TRUE_STR);
            //  设置城市
            DistrictPO districtPO = DistrictCache.getByName(userRegisterPO.getAreaName());
            apiUserRequest.setCity(userRegisterPO.getAreaName());
            apiUserRequest.setAreaCode(userRegisterPO.getAreaCode());
            apiUserRequest.setProvinceCode(districtPO.getProvinceCode());
            apiUserRequest.setProvinceName(districtPO.getProvinceName());

            //  记录流程
            ProductApplyFlowPO insertProductApplyFlowPO = new ProductApplyFlowPO();
            insertProductApplyFlowPO.setApiClientId(lastDataExchangeFlow.getApiClientId());
            insertProductApplyFlowPO.setLoanChannelId(lastDataExchangeFlow.getLoanChannelId());
            insertProductApplyFlowPO.setLoanProductId(lastDataExchangeFlow.getLoanProductId());
            insertProductApplyFlowPO.setLoanProductPlanId(lastDataExchangeFlow.getLoanProductPlanId());
            insertProductApplyFlowPO.setReqId(lastDataExchangeFlow.getReqId());
            insertProductApplyFlowPO.setSrcType(ProductApplyFlowSrcTypeEnum.API.getType());
            insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.APPLY_ERROR.getType());
            insertProductApplyFlowPO.setPhoneMd5(lastDataExchangeFlow.getPhoneMd5());
            insertProductApplyFlowPO.setCreateTime(DateUtils.currentTime());
            insertProductApplyFlowPO.setBizStatus("0");
            insertProductApplyFlowPO.setAreaName(apiUserRequest.getCity());
            insertProductApplyFlowPO.setAreaCode(apiUserRequest.getAreaCode());

            try {
                //  本地机构
                if (productPlanTypeService.hasLocalOrgPlan(finalProductPO, finalProductPlanPO)) {
                    insertProductApplyFlowPO.setCallUrl("本地甲方CRM");
                }

                //  API机构
                if (productPlanTypeService.hasApiOrgPlan(finalProductPO, finalProductPlanPO)) {
                    Long reqId = insertProductApplyFlowPO.getReqId();
                    //  设置API参数数据
                    apiUserRequest.setProductId(insertProductApplyFlowPO.getLoanProductId());
                    apiUserRequest.setProductPlanId(insertProductApplyFlowPO.getLoanProductPlanId());
                    apiUserRequest.setLoanChannelId(insertProductApplyFlowPO.getLoanChannelId());
                    apiUserRequest.setReqId(reqId.toString());

                    //  发送进件
                    ApiHttpMessage httpMessage = apiPlanHttpHandler.sendApply(apiUserRequest, finalProductPO, finalProductPlanPO);
                    insertProductApplyFlowPO.setCallUrl(finalProductPO.getApiApplyUrl());
                    insertProductApplyFlowPO.setReqData(String.valueOf(httpMessage.getRequestBody()));
                    insertProductApplyFlowPO.setRespData(httpMessage.getResponseBody());
                    insertProductApplyFlowPO.setRespCode(String.valueOf(httpMessage.getRespCode()));

                    //  是否返回HTTP异常
                    boolean hasHttpExp = apiBizRequiredService.hasHttpExp(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.APPLY_ERROR);
                    if (hasHttpExp) {
                        return ;
                    }
                    //  是否进件返回失败
                    boolean hasHttpRespBizSuc = apiBizRequiredService.hasHttpRespBizSuc(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.APPLY_ERROR);
                    if (!hasHttpRespBizSuc) {
                        return ;
                    }
                }

                //  记录流程数据
                insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.USER_ACCEPT.getType());
                insertProductApplyFlowPO.setBizStatus("1");
                productApplyFlowService.insert(insertProductApplyFlowPO, false);

                //  记录账单
                ProductAmountBO productAmountBO = new ProductAmountBO();
                productAmountBO.setProductId(finalProductPlanPO.getLoanProductId());
                productAmountBO.setProductPlanId(finalProductPlanPO.getId());
                productAmountBO.setUserId(userRegisterPO.getId());
                productAmountBO.setPhoneMd5(userRegisterPO.getPhoneMd5());
                productAmountBO.setLoanChannelId(lastDataExchangeFlow.getLoanChannelId());
                productAmountBO.setApiClientId(lastDataExchangeFlow.getApiClientId());
                productAmountBO.setOriginalPrice(null);
                productAmountBO.setHasPlatform(Boolean.FALSE);
                productAmountBO.setHasLocalExist(Boolean.TRUE);
                BigDecimal planPrice = productAmountService.deduct(productAmountBO);

                ApiKeyAmountBO apiKeyAmountBO = new ApiKeyAmountBO();
                apiKeyAmountBO.setProductId(finalProductPlanPO.getLoanProductId());
                apiKeyAmountBO.setProductPlanId(finalProductPlanPO.getId());
                apiKeyAmountBO.setUserId(userRegisterPO.getId());
                apiKeyAmountBO.setLoanChannelId(lastDataExchangeFlow.getLoanChannelId());
                apiKeyAmountBO.setApiClientId(lastDataExchangeFlow.getApiClientId());
                apiKeyAmountBO.setPhoneMd5(userRegisterPO.getPhoneMd5());
                apiKeyAmountBO.setPlanPrice(planPrice);
                apiKeyAmountBO.setHasPlatform(Boolean.FALSE);
                apiKeyAmountBO.setHasLocalExist(Boolean.TRUE);
                apiKeyAmountService.deduct(apiKeyAmountBO);
            } catch (Exception e) {
                StringBuilder sb = StringUtils.createBuilder(e).append("\n");
                StackTraceElement[] stackTrace = e.getStackTrace();

                for (int i = 0; i < stackTrace.length; i++) {
                    StackTraceElement stackTraceElement = stackTrace[i];
                    sb.append("\t" + stackTraceElement).append("\n");
                }

                //  记录异常数据
                insertProductApplyFlowPO.setExceptionMsg("机构分发2异常");
                insertProductApplyFlowPO.setStackMsg(sb.toString());
                productApplyFlowService.insert(insertProductApplyFlowPO, false);
            }
        });
    }
}
